import tkinter as tk
from pynput import mouse
import math


class OverlayWindow:
    def __init__(self, root):
        # 初始化主窗口
        self.root = root

        # 获取屏幕尺寸
        self.screen_width = self.root.winfo_screenwidth()
        self.screen_height = self.root.winfo_screenheight()

        # 创建遮罩窗口
        self.overlay = tk.Toplevel(self.root)
        self.overlay.withdraw()
        self.overlay.attributes('-fullscreen', True)
        self.overlay.attributes('-topmost', True)
        self.overlay.attributes('-alpha', 0.0)
        self.overlay.overrideredirect(True)

        # 创建Canvas
        self.canvas = tk.Canvas(
            self.overlay,
            width=self.screen_width,
            height=self.screen_height,
            highlightthickness=0,
            bg='black'
        )
        self.canvas.pack(fill='both', expand=True)

        # 状态变量
        self.is_active = False
        self.animation_running = False
        self.animation_interrupted = False
        self.circle_radius = 40
        self.animation_steps = 120
        self.animation_speed = 16
        self.target_alpha = 0.25
        self.highlight_circle = None
        self.mouse_listener = None

        # 添加抗锯齿缓存
        self.last_radius = None
        self.last_position = None

    def round_coordinates(self, value):
        """确保坐标为整数，避免抖动"""
        return round(value)

    def ease_out_quint(self, t):
        """五次方缓动函数，提供更平滑的过渡"""
        return 1 - pow(1 - t, 5)

    def create_glow_circle(self, x, y, radius, intensity=1.0):
        """创建更平滑的发光圆圈，消除抖动"""
        # 确保所有坐标都是整数
        x = self.round_coordinates(x)
        y = self.round_coordinates(y)
        radius = self.round_coordinates(radius)

        # 只在位置或大小发生实际变化时更新
        if (self.last_position == (x, y) and
                self.last_radius == radius and
                not self.animation_running):
            return

        # 更新位置和半径缓存
        self.last_position = (x, y)
        self.last_radius = radius

        # 清除旧的圆圈
        self.canvas.delete("circle")

        # 外部光晕层（最弱）
        outer_radius = self.round_coordinates(radius * 1.1)
        self.canvas.create_oval(
            x - outer_radius,
            y - outer_radius,
            x + outer_radius,
            y + outer_radius,
            fill='',
            outline='white',
            width=1,
            tags="circle"
        )

        # 主要圆圈
        self.canvas.create_oval(
            x - radius,
            y - radius,
            x + radius,
            y + radius,
            fill='white',
            outline='white',
            width=2,
            tags="circle"
        )

        # 内部发光层
        inner_radius = self.round_coordinates(radius * 0.9)
        inner_width = max(1, self.round_coordinates(2 * intensity))
        self.canvas.create_oval(
            x - inner_radius,
            y - inner_radius,
            x + inner_radius,
            y + inner_radius,
            fill='white',
            outline='white',
            width=inner_width,
            tags="circle"
        )

    def show_animation(self, step=0):
        if step == 0:
            self.root.after(0, self.overlay.deiconify)
            self.animation_interrupted = False
            self.last_radius = None
            self.last_position = None

        # 检查是否被打断
        if self.animation_interrupted:
            self.animation_running = False
            self.is_active = False
            self.root.after(0, self.overlay.withdraw)
            self.canvas.delete("circle")
            return

        if step <= self.animation_steps:
            # 计算总体进度
            progress = step / self.animation_steps

            # 使用相同的缓动函数计算所有动画元素
            eased_progress = self.ease_out_quint(progress)

            # 同步更新背景透明度
            alpha = eased_progress * self.target_alpha
            self.root.after(0, lambda: self.overlay.attributes('-alpha', alpha))

            # 计算当前圆圈大小（使用对数插值使变化更平滑）
            max_radius = math.sqrt(self.screen_width ** 2 + self.screen_height ** 2) / 2
            min_radius = self.circle_radius

            # 使用对数插值计算半径，并确保结果为整数
            log_max = math.log(max_radius)
            log_min = math.log(min_radius)
            current_log = log_max + (log_min - log_max) * eased_progress
            current_radius = self.round_coordinates(math.exp(current_log))

            # 获取鼠标位置
            x, y = self.root.winfo_pointerxy()

            # 创建发光圆圈（强度随进度变化）
            self.create_glow_circle(x, y, current_radius, eased_progress)

            # 继续动画
            self.root.after(self.animation_speed,
                            lambda: self.show_animation(step + 1))
        else:
            self.animation_running = False
            self.is_active = True

    def hide_animation(self, alpha=None):
        if alpha is None:
            alpha = self.target_alpha

        if alpha <= 0:
            self.root.after(0, lambda: self.overlay.withdraw())
            self.is_active = False
            self.canvas.delete("circle")
        else:
            # 使用平滑的缓动
            eased_alpha = self.ease_out_quint(alpha / self.target_alpha) * self.target_alpha
            self.root.after(0, lambda: self.overlay.attributes('-alpha', eased_alpha))
            self.root.after(16, lambda: self.hide_animation(alpha - 0.03))

    def show(self):
        if not self.is_active and not self.animation_running:
            # 创建新的鼠标监听器
            if self.mouse_listener is None:
                self.mouse_listener = mouse.Listener(on_click=self.on_click)
                self.mouse_listener.start()

            self.animation_running = True
            self.animation_interrupted = False
            self.show_animation()

    def hide(self):
        if self.is_active or self.animation_running:
            # 停止鼠标监听器
            if self.mouse_listener is not None:
                self.mouse_listener.stop()
                self.mouse_listener = None

            # 如果动画正在运行，直接打断
            if self.animation_running:
                self.animation_interrupted = True
            else:
                self.root.after(0, self.hide_animation)

    def update_cursor_position(self):
        """更新光标位置"""
        if self.is_active and not self.animation_running:
            x, y = self.root.winfo_pointerxy()
            self.create_glow_circle(x, y, self.circle_radius, 1.0)

        # 持续更新，使用较小的延迟以确保平滑跟随
        self.root.after(5, self.update_cursor_position)

    def show(self):
        """显示效果"""
        if not self.is_active and not self.animation_running:
            # 创建新的鼠标监听器
            if self.mouse_listener is None:
                self.mouse_listener = mouse.Listener(on_click=self.on_click)
                self.mouse_listener.start()

            self.animation_running = True
            self.animation_interrupted = False
            self.show_animation()

            # 启动位置更新
            self.update_cursor_position()

    def on_click(self, x, y, button, pressed):
        if button == mouse.Button.left and pressed:
            self.root.after(0, self.hide)
            return False  # 停止监听器